/**
 * 联合类型
 */
function padLeft(value: string, padding: any) {
  if (typeof padding === "number") {
    console.log(Array(padding + 1).join("2"));
    return Array(padding + 1).join("1") + value;
  }
  if (typeof padding === "string") {
    return padding + value;
  }
  throw new Error(`Expected string or number, got '${typeof padding}'.`);
}
let aTo1: string = padLeft("Hello", 4)
console.log(aTo1);
// 编译时通过但是运行时失败。
// let aTo2:string = padLeft("Hello World",true) //期望的字符串或数字，得到“布尔值”。
// console.log(aTo2);

function padLeftTo1(value: string, padding: string | number) {  //使用联合类型取代any
  if (typeof padding === "number") {
    console.log(Array(padding + 1).join("2"));
    return Array(padding + 1).join("1") + value;
  }
  if (typeof padding === "string") {
    return padding + value;
  }
  throw new Error(`Expected string or number, got '${typeof padding}'.`);
}
// let aTo2:string = padLeftTo1("Hello World",true)  //类型“boolean”的参数不能赋给类型“string | number”的参数。

/**
 * 具有公共字段的联合
 */
interface Bird {
  fly(): void;
  layEggs(): void;
}
interface Fish {
  swim(): void;
  layEggs(): void;
}
// declare function getSmallPet(): Fish | Bird 
// let pet = getSmallPet()
// pet.layEggs();
// pet.swim()  //类型“Fish | Bird”上不存在属性“swim”。  类型“Bird”上不存在属性“swim”。

/**
 * 可区分联合
 */
type NetWorkLoadingState = {
  state: "loading";
}
type NetWorkFailedState = {
  state: "failed";
  code: string;
}
type NetWorkSuccessState = {
  state: "success";
  response: {
    title: string;
    duration: number;
    summary: string;
  }
}
type NetWorkState = NetWorkLoadingState | NetWorkFailedState | NetWorkSuccessState;
function logger(state: NetWorkState): string {
  switch (state.state) {
    case "loading":
      return "Downloading...";
    case "failed":
      return `Error ${state.code} downloading`;
    case "success":
      return `Downloaded ${state.response.title}---${state.response.summary}`;
    default:
      return "string"
  }
}
let log = logger({ state: "loading" })
console.log(log);

/**
 * 联合的穷尽性检查
 */
type NetworkLoadingState = { state: "loading" };
type NetworkFailedState = { state: "failed"; code: number };
type NetworkSuccessState = { state: "success" };
type NetworkFromCachedState = { state: "from_cache" };

type NetworkState =
  | NetworkLoadingState
  | NetworkFailedState
  | NetworkSuccessState
  | NetworkFromCachedState;

function assertNever(x: unknown): never {
  throw new Error("Unexpected object: " + x);
}

function loggerTo1(s: NetworkState): string {
  switch (s.state) {
    case "loading":
      return "loading request";
    case "failed":
      return `failed with code ${s.code}`;
    case "success":
      return "got response";
    // case "from_cache":
    //   return "got response";
    default:
      return assertNever(s);
  }
}
// let logTo1 = loggerTo1({ state: "from_cache" }) //编译后报错

/**
 * 交叉类型 —— &
 */
interface ErrorHandling {
  success: boolean;
  error?: { message: string };
}

interface ArtworksData {
  artworks: { title: string }[];
}

interface ArtistsData {
  artists: { name: string }[];
}

// 这些接口被组合后拥有一致的错误处理，和它们自己的数据

type ArtworksResponse = ArtworksData & ErrorHandling;
type ArtistsResponse = ArtistsData & ErrorHandling;

const handleArtistsResponse = (response: ArtistsResponse) => {
  if (response.error) {
    console.error(response.error.message);
    return;
  }

  console.log(response.artists);
};